﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Moq;
using FriendsNearby.Services;
using System.ComponentModel.Design;
using FriendsNearby.Services.Entities;
using Twitter.Tests;
using Twitter;
using System.Linq.Expressions;

namespace FriendsNearbyBot.Tests
{
	[TestFixture]
	public class FriendsQueryProcessorFixture : TestBase
	{
		Guid me = Guid.Empty;

		Mock<IPeopleNearbyService> peopleNearbyService;
		Mock<IUsersService> usersService;

		[SetUp]
		public void CreateServices()
		{
			peopleNearbyService = new Mock<IPeopleNearbyService>();
			usersService = new Mock<IUsersService>();
		}

		[Test]
		public void ShouldListAllDirectFriends()
		{
			usersService.Expect(x => x.QueryUserRegistry(It.IsAny<Expression<Func<UserRegistry, bool>>>())).Returns(new UserRegistry { UserID = me });
			peopleNearbyService.Expect(x => x.GetContacts(me, QueryContactsKind.Direct)).Returns(new PersonNearby[]{
                new PersonNearby() { DisplayName = "user1" , Distance = 1 },
                new PersonNearby() { DisplayName = "user2" , Distance = 2 }
            });

			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());
			processor.Process(bot, CreateMessage("list all", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			AssertString.StartsWith("user1:1 Km.;", user.Messages.GetAll().First().Text);
		}

		[Test]
		public void ShouldDoLikeSearchBetweenFriends()
		{
			usersService.Expect(x => x.QueryUserRegistry(It.IsAny<Expression<Func<UserRegistry, bool>>>())).Returns(new UserRegistry { UserID = me });
			peopleNearbyService.Expect(x => x.GetContacts(me, QueryContactsKind.Direct)).Returns(new PersonNearby[]{
                new PersonNearby() { DisplayName = "Another User" , Distance = 1 },
                new PersonNearby() { DisplayName = "Joanne Goldstein" , Distance = 1 },
                new PersonNearby() { DisplayName = "Edward Johanson" , Distance = 2 },
                new PersonNearby() { DisplayName = "Harry" , Distance = 3 },
                new PersonNearby() { DisplayName = "Jo Smith" , Distance = 4 }
            });

			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());
			processor.Process(bot, CreateMessage("search jo", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.That(user.Messages.GetAll().First().Text.Contains("Joanne Goldstein:1 Km.;"));
			Assert.That(user.Messages.GetAll().First().Text.Contains("Edward Johanson:2 Km.;"));
			Assert.That(user.Messages.GetAll().First().Text.Contains("Jo Smith:4 Km.;"));
			Assert.IsFalse(user.Messages.GetAll().First().Text.Contains("Another User"));
			Assert.IsFalse(user.Messages.GetAll().First().Text.Contains("Harry"));
		}

		[Test]
		public void RandomMessageAllowsNextProccessor()
		{
			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());
			var result = processor.Process(bot, CreateMessage("blah", user.ScreenName, bot.ScreenName));
			Assert.AreEqual(RunNextProcessor.Yes, result);

			Assert.AreEqual(0, user.Messages.GetAll().Count());
		}

		[Test]
		public void SearchWithoutCriteriaProduceNoMessage()
		{
			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());

			var result = processor.Process(bot, CreateMessage("search", user.ScreenName, bot.ScreenName));
			Assert.AreEqual(RunNextProcessor.Yes, result);

			Assert.AreEqual(0, user.Messages.GetAll().Count());
		}

		[Test]
		public void SearchNotNormalizedWithoutCriteriaProduceNoMessage()
		{
			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());

			var result = processor.Process(bot, CreateMessage("  SeArch  ", user.ScreenName, bot.ScreenName));
			Assert.AreEqual(RunNextProcessor.Yes, result);

			Assert.AreEqual(0, user.Messages.GetAll().Count());
		}

		[Test]
		public void ShouldShowNiceEmptyMessage()
		{
			usersService.Expect(x => x.QueryUserRegistry(It.IsAny<Expression<Func<UserRegistry, bool>>>())).Returns(new UserRegistry { UserID = me });
			peopleNearbyService.Expect(x => x.GetContacts(me, QueryContactsKind.Direct)).Returns(new PersonNearby[] { });

			// Warn: 
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtestb");
			bot.SetBuddy(user);
			user.SetBuddy(bot);

			FriendsQueryProcessor processor = new FriendsQueryProcessor(usersService.Object, peopleNearbyService.Object, CreateMessageBuilder());
			processor.Process(bot, CreateMessage("list all", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.That(user.Messages.GetAll().First().Text.Contains("There are no people to list"));
		}
	}
}
